<template>
  <AdVxeModal
    v-bind="$attrs"
    @register="register"
    :id="formIndex"
    :title="title ? `${title} - ${FormModeEntityRef.Display}` : FormModeEntityRef.Display"
    :cancelText="cancelText ? cancelText : t('common.cancelText')"
    :close-func="handleClose"
    :okText="okText ? okText : FormModeEntityRef.OkBtnTitle"
    @ok="handleOk"
    @open-change="handleOpenChange"
  >
    <BasicForm @register="registerForm" @contextmenu="handleContextMenu" />
  </AdVxeModal>

  <PrintTemplateModal @register="templateModalRegister" v-bind="templateModalProps" />
</template>
<script lang="ts" setup>
  import type { PropType } from 'vue';
  import { ref } from 'vue';
  import { AdVxeModal, useModalInner } from '@/components/AdVxeModal';
  import { BasicForm, useForm, FormSchema } from '@/components/Form';
  import { PrintTemplateModal, useAdPrint } from '@/components/AdPrint';

  import { useI18n } from '@/hooks/web/useI18n';
  import { useMessage } from '@/hooks/web/useMessage';
  import { useContextMenu } from '@/hooks/web/useContextMenu';
  import { destroyContextMenu } from '@/components/ContextMenu';

  import { isFunction } from '@/utils/is';
  import { propTypes } from '@/utils/propTypes';

  import { FormModeEnum, FormModeEntity } from '@/enums/formEnum';

  import type { FetchParams } from '../types/table';

  defineOptions({ name: 'DetailFormModal' });
  const props = defineProps({
    /** 表单标识 */
    formIndex: propTypes.string,
    /** 主键字段 */
    keyField: propTypes.string.def('Id'),
    /** 表单抬头 */
    title: propTypes.string,
    /** 关闭按钮文本 */
    cancelText: propTypes.string,
    /** 确认按钮文本 */
    okText: propTypes.string,
    /** 表单架构 */
    formSchema: {
      type: [Array] as PropType<FormSchema[]>,
      default: () => [],
    },
    /** 扩展 form 组件，增加 label 宽度，表单内所有组件适用，可以单独在某个项覆盖或者禁用 */
    labelWidth: {
      type: [Number, String] as PropType<number | string>,
      default: null,
    },
    /** label 布局 */
    labelAlign: {
      type: String as PropType<'left' | 'right'>,
      default: null,
    },
    /** 紧凑类型表单，减少 margin-bottom */
    compact: propTypes.bool.def(true),
    /** 向表单内所有组件传递 size 参数,自定义组件需自行实现 size 接收 */
    formSize: {
      type: String as PropType<'default' | 'small' | 'large'>,
      default: null,
    },
    /** 向表单内所有组件传递 disabled 属性，自定义组件需自行实现 disabled 接收 */
    disabled: propTypes.bool,
    /** 实体新增接口请求对象 */
    createApi: {
      type: Function as PropType<(params: any[]) => Promise<any>>,
      default: null,
    },
    /** 实体更新接口请求对象 */
    updateApi: {
      type: Function as PropType<(params: any[]) => Promise<any>>,
      default: null,
    },
    /** 实体删除接口请求对象 */
    deleteApi: {
      type: Function as PropType<(params: any[]) => Promise<any>>,
      default: null,
    },
    /** 关闭回调，返回true关闭窗体 */
    closeFn: {
      type: Function as PropType<(formMode: FormModeEnum, record: any) => Promise<boolean>>,
      default: null,
    },
    /** 提交回调，返回true关闭窗体 */
    submitFn: {
      type: Function as PropType<(formMode: FormModeEnum, record: any) => Promise<boolean>>,
      default: null,
    },
    /** 重新加载表格数据函数 */
    reloadFn: {
      type: Function as PropType<(opt?: FetchParams) => Promise<void>>,
      default: null,
    },
  });

  const { t } = useI18n();
  const { createMessage } = useMessage();
  const [createContextMenu] = useContextMenu();

  const formModeRef = ref<FormModeEnum>(FormModeEnum.Ok);
  const FormModeEntityRef = ref<FormModeEntity>(new FormModeEntity(formModeRef.value));

  // console.log('setup', props);
  const [registerForm, { resetFields, getFieldsValue, setFieldsValue, validate }] = useForm({
    /** 表单配置 */
    schemas: props.formSchema,
    /** 扩展 form 组件，增加 label 宽度，表单内所有组件适用，可以单独在某个项覆盖或者禁用 */
    labelWidth: props.labelWidth,
    /** label 布局 */
    labelAlign: props.labelAlign,
    /** 紧凑类型表单，减少 margin-bottom */
    compact: props.compact,
    /** 向表单内所有组件传递 size 参数,自定义组件需自行实现 size 接收 */
    size: props.formSize,
    /** 向表单内所有组件传递 disabled 属性，自定义组件需自行实现 disabled 接收 */
    disabled: props.disabled,
    /** 是否显示操作按钮(重置/提交) */
    showActionButtonGroup: false,
  });

  const [register, { setModalProps, closeModal, changeLoading }] = useModalInner(async (data) => {
    changeLoading(true);
    try {
      await resetFields();
      if (data.formMode) {
        formModeRef.value = data.formMode as FormModeEnum;
        FormModeEntityRef.value = new FormModeEntity(formModeRef.value);
      }
      if (data.record) {
        await setFieldsValue({
          ...data.record,
        });
      }
    } finally {
      changeLoading(false);
    }
  });

  //#region "加载状态"
  const loadingRef = ref(false);
  /** 开启加载状态 */
  function openLoading() {
    changeLoading(true);
    setModalProps({ okLoading: true, cancelLoading: true });
    loadingRef.value = true;
  }
  /** 关闭加载状态 */
  function closeLoading() {
    changeLoading(false);
    setModalProps({ okLoading: false, cancelLoading: false });
    loadingRef.value = false;
  }
  //#endregion
  //#region 定义高级打印
  const { printContextMenus, templateModalRegister, templateModalProps } = useAdPrint({
    formIndex: props.formIndex,
    keyField: props.keyField,
    getFormData: () => getFieldsValue(),
  });
  /** 处理上下文菜单(右键菜单) */
  function handleContextMenu(e: MouseEvent) {
    const element = document.elementFromPoint(e.clientX, e.clientY) as Element;
    const cursor = document.defaultView?.getComputedStyle(element, null).cursor;
    // console.log('handleContextMenu', {
    //   cursor: cursor,
    // });

    let items: any[] = [];
    switch (FormModeEntityRef.value.FormMode) {
      case FormModeEnum.Ok:
      case FormModeEnum.Edit:
      case FormModeEnum.ReadOnly:
        if (!cursor || cursor === 'default' || cursor === 'auto') {
          items = [...printContextMenus];
        }
        break;
    }
    if (items && items?.length > 0) {
      createContextMenu({
        event: e,
        styles: {
          border: '1px solid #eee',
          'border-radius': '2px',
          'box-shadow': '3px 3px 3px rgb(0 0 0 / 15%)',
        },
        items: [...items],
      });
    }
  }
  //#endregion

  /** 处理关闭按钮 */
  async function handleClose() {
    openLoading();

    const { closeFn } = props;
    try {
      if (closeFn && isFunction(closeFn)) {
        const result = await closeFn(FormModeEntityRef.value.FormMode, getFieldsValue());
        return result;
      }
    } finally {
      closeLoading();
    }
    return true;
  }
  /** 处理确定按钮 */
  async function handleOk() {
    const data = await validate();
    if (!data) return;
    //console.log(data);

    openLoading();

    const { createApi, updateApi, deleteApi, submitFn, reloadFn } = props;
    try {
      if (submitFn && isFunction(submitFn)) {
        const canClose = await submitFn(FormModeEntityRef.value.FormMode, getFieldsValue());
        if (canClose) {
          closeModal();
        }
      } else {
        switch (FormModeEntityRef.value.FormMode) {
          case FormModeEnum.Ok:
          case FormModeEnum.ReadOnly:
            closeModal();
            break;
          case FormModeEnum.Add:
            if (createApi && isFunction(createApi)) {
              const result = await createApi([getFieldsValue()]);
              closeModal();
              if (reloadFn && isFunction(reloadFn)) {
                await reloadFn();
              }
              if (result?.Type === 200) {
                createMessage.success(t('common.successText'));
              }
            }
            break;
          case FormModeEnum.Edit:
            if (updateApi && isFunction(updateApi)) {
              const result = await updateApi([getFieldsValue()]);
              closeModal();
              if (reloadFn && isFunction(reloadFn)) {
                await reloadFn();
              }
              if (result?.Type === 200) {
                createMessage.success(t('common.successText'));
              }
            }
            break;
          case FormModeEnum.Delete:
            if (deleteApi && isFunction(deleteApi)) {
              const formData = getFieldsValue();
              const result = await deleteApi([formData.Id]);
              closeModal();
              if (reloadFn && isFunction(reloadFn)) {
                await reloadFn();
              }
              if (result?.Type === 200) {
                createMessage.success(t('common.successText'));
              }
            }
            break;
          case FormModeEnum.Search:
            closeModal();
            break;
        }
      }
    } finally {
      closeLoading();
    }
  }
  /** 打开或者关闭触发 */
  function handleOpenChange(open: boolean) {
    if (!open) {
      destroyContextMenu();
    }
  }
</script>
<style lang="less">
  .context-menu {
    z-index: 8888 !important;
  }
</style>
